#ifndef APRIORI_H
#define APRIORI_H

#include <boost/shared_ptr.hpp>
#include <list>
#include <map>

#include "itemset_container.h"
#include "itemset.h"

using namespace boost;
using namespace std;

/**
 * In this namespace all classes included, which are implementing the 
 * apriori algorithm.
 * \version 0.1
 * \author Michael Opitz
 */
namespace apriori {
	template <class transaction,
		  template <class> class collection
		 >
	/**
	 * The main-class which implements the apriori-algorithm. 
	 * This class takes 2 template parameters. The first is the type
	 * of the transaction, which elements must implement the ==-operator, 
	 * and the class itself must implement the get_elements-method. 
	 * The second parameter declares the collection (list, vector, ...), 
	 * in which the transactions are stored. The collection must be
	 * iterateable (define ::iterator, begin() and end() method).
	 * \author Michael Opitz
	 * \version 0.1
	 */
	class apriori_alg {
	public:
		// declare a few types:
		typedef typename transaction::ptr trans_ptr;
		typedef collection<trans_ptr> coll;

		typedef itemset_container<transaction, collection> t_itemset_c;
		typedef typename t_itemset_c::t_item t_item;

		// here we go
		//! The standard-constructor, which initializes the algorithm
		/**
		 * The standard-constructor, which initializes the algorithm
		 * \param trans is a collection of transactions
		 * \param mins is the minimal support value
		 * \param minc is the minimal confidence value (not supported!!)
		 */
		apriori_alg(const coll &trans, int mins, float minc)
		: _db(trans), _mins(mins), _minc(minc) {}
		~apriori_alg() {}

		//! Executes the algorithm
		/**
		 * Executes the algorithm.
		 * The results are stored in _result, and can be retrieved
		 * through getter methods.
		 */
		void doit()
		{
			_itemsets.initialize(_db);
			_itemsets.cut(_mins, _minc);
			list<t_item> prev;
			while(_itemsets.get_items().size() != 0) {
				prev = _itemsets.get_items();
				_itemsets.generate(_db);
				_itemsets.cut(_mins, _minc);
			}
			_result = prev;
		}

		list<t_item>& get_result() {return _result;}
		const list<t_item>& get_result() const {return _result;}
	private:
		//! transactions
		coll _db;
		//! minimal support value
		int _mins;
		//! minimal confidence value
		float _minc;

		//! collection of the itemsets (of type itemset_container)
		t_itemset_c _itemsets;
		//! collection of the result
		list<t_item> _result;
	};
}

#endif
